package com.ziyucoding.springboot.labs.lab4.concurrentdemo.example.deadlock;

import lombok.extern.slf4j.Slf4j;

/**
 * 死锁 示例1
 * 当DeadLockExample1类的对象flag==1时（example1），先锁定lock1,睡眠3秒
 * 而example1在睡眠的时候另一个flag==0的对象（example2）线程启动，先锁定lock1,睡眠3秒
 * example1睡眠结束后需要锁定lock2才能继续执行，而此时lock2已被example2锁定；
 * example2睡眠结束后需要锁定lock1才能继续执行，而此时lock1已被example1锁定；
 * example1、example2相互等待，都需要得到对方锁定的资源才能继续执行，从而死锁。
 *
 * @author ziyucoding
 * @date 2022-10-29
 **/
@Slf4j
public class DeadLockExample1 implements Runnable {

    public int flag = 1;

    private static Object lock1 = new Object();

    private static Object lock2 = new Object();

    public static void main(String[] args) {
        DeadLockExample1 example1 = new DeadLockExample1();
        example1.flag = 1;
        DeadLockExample1 example2 = new DeadLockExample1();
        example2.flag = 0;
        //example1、example2都处于可执行状态，但JVM线程调度先执行哪个线程是不确定的。
        //example2的run()可能在example1的run()之前运行
        new Thread(example1).start();
        new Thread(example2).start();
    }


    @Override
    public void run() {
        log.info("flag:{}", flag);
        if (flag == 1) {
            synchronized (lock1) {
                try {
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                    log.error("发生异常", e);
                }

                synchronized (lock2) {
                    log.info("1");
                }
            }
        }

        if (flag == 0) {
            synchronized (lock2) {
                try {
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                    log.error("发生异常", e);
                }
                synchronized (lock1) {
                    log.info("0");
                }
            }
        }
    }
}
